parser grammar FlexParser;

options {
    tokenVocab = FlexLexer;
}

@parser::header {
    package pl.practica5Modi;
}

@parser::members {

  List<RecognitionException> errors = new ArrayList<RecognitionException>();

  public List<RecognitionException> getAllErrors() {
      return new ArrayList<RecognitionException>(errors);
  }
 
  public boolean hasErrors() {
      return !errors.isEmpty();
  }
  
  @Override
  public void reportError(RecognitionException e) {
      displayRecognitionError(this.getTokenNames(), e);
      errors.add(e);
  }
  
}


// Analizador Sintactico
flex: definiciones SEPARA_BLOQUE reglas SEPARA_BLOQUE funciones EOF;


//------------------------------------------------------------------------------------------//

definiciones: defineTokens seccionDefinicionIds;

defineTokens: definicionToken1 definicionToken2;

definicionToken1: id rango;
rango: CORCHETE_ABIERTO rangoDigito CORCHETE_CERRADO;
rangoDigito: DIGITO GUION DIGITO;

definicionToken2: id rangoMayusculaMinuscula;
rangoMayusculaMinuscula: CORCHETE_ABIERTO rangoMayuscula rangoMinuscula CORCHETE_CERRADO;
rangoMayuscula: LETRA_MAYUSCULA GUION LETRA_MAYUSCULA;
rangoMinuscula: LETRA_MINUSCULA GUION LETRA_MINUSCULA;

seccionDefinicionIds: DECLARACION_ABIERTA definicionId definicionId DECLARACION_CERRADA;
definicionId: INT id PUNTO_COMA;

id: (ID | LETRA_MINUSCULA);

//------------------------------------------------------------------------------------------//

reglas: regla1 regla2;

regla1: expresion1 accion;
expresion1: base disyuncion ASTERISCO;
disyuncion: PARENTESIS_ABIERTO base DISYUNCION base PARENTESIS_CERRADO;

regla2: expresion2 accion;
expresion2: base MAS;

base: LLAVE_ABIERTA id LLAVE_CERRADA;

accion: id INCREMENTAR PUNTO_COMA;

//------------------------------------------------------------------------------------------//

funciones: funcion1 funcion2;

funcion1: cabeceraFuncion1 LLAVE_ABIERTA sentenciaReturn LLAVE_CERRADA;
cabeceraFuncion1: INT id PARENTESIS_ABIERTO VOID PARENTESIS_CERRADO;
sentenciaReturn: RETURN DIGITO PUNTO_COMA;

funcion2: cabeceraFuncion2 LLAVE_ABIERTA sentencias LLAVE_CERRADA;
cabeceraFuncion2: INT id PARENTESIS_ABIERTO parametro1 COMA parametro2 PARENTESIS_CERRADO;
parametro1: INT id;
parametro2: CHAR ASTERISCO id CORCHETE_ABIERTO CORCHETE_CERRADO;

sentencias: sentenciaFopen asignacion asignacion llamada1 llamada2 sentenciaPrintf sentenciaPrintf sentenciaReturn;
sentenciaFopen: id IGUALAR id PARENTESIS_ABIERTO id CORCHETE_ABIERTO DIGITO CORCHETE_CERRADO COMA STRING PARENTESIS_CERRADO PUNTO_COMA;
asignacion: id IGUALAR DIGITO PUNTO_COMA;
llamada1: id PARENTESIS_ABIERTO PARENTESIS_CERRADO PUNTO_COMA;
llamada2: id PARENTESIS_ABIERTO id PARENTESIS_CERRADO PUNTO_COMA;
sentenciaPrintf: id PARENTESIS_ABIERTO STRING COMA id PARENTESIS_CERRADO PUNTO_COMA;